package com.wswy.wzcx.ui.module.lbs

import android.arch.lifecycle.Observer
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Bundle
import android.view.View
import com.airbnb.lottie.LottieProperty
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationListener
import com.amap.api.maps2d.AMap
import com.amap.api.maps2d.CameraUpdateFactory
import com.amap.api.maps2d.LocationSource
import com.amap.api.maps2d.model.*
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.core.PoiItem
import com.blankj.utilcode.util.SizeUtils
import com.che.libcommon.utils.MapUtils
import com.che.libcommon.utils.view.FABUtils
import com.wswy.wzcx.AppContext
import com.wswy.wzcx.R
import com.wswy.wzcx.module.LocManager
import com.wswy.wzcx.module.base.CBaseFragment
import com.wswy.wzcx.module.base.gone
import com.wswy.wzcx.module.base.visible
import kotlinx.android.synthetic.main.fragment_lbs_map.*
import timber.log.Timber

open class LbsBaseMapFragment :CBaseFragment() , LocationSource, AMapLocationListener,
        AMap.OnCameraChangeListener,
        AMap.OnMarkerClickListener{


    private lateinit var sensorHelper: SensorEventHelper

    private var mListener: LocationSource.OnLocationChangedListener? = null
    private var amaplocationClient: AMapLocationClient? = null
    private var firstFix = false

    private var mLocMarker: Marker? = null
    private var mCircle: Circle? = null


    private var mLocLatLng: LatLng?=null
    private var markerOverlay:GasPoiOverlay?=null

    protected lateinit var lbsViewModel: LbsViewModel


    override fun getContentLayoutId(): Int {
        return R.layout.fragment_lbs_map
    }
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        mapView?.onCreate(savedInstanceState)

        sensorHelper = SensorEventHelper(AppContext.getContext())

        lbsViewModel = provideViewModel(LbsViewModel::class.java)


        lbsViewModel.getGasListLiveData().observe(this, Observer {
            showPoints(it)
        })


        fab_navigation.setImageBitmap(FABUtils.createBitmap(requireContext(), R.drawable.map_navigation,
                SizeUtils.dp2px(17f),
                SizeUtils.dp2px(23f),
                getString(R.string.map_navigation), 14f, Color.WHITE
        ))

        fab_navigation.setOnClickListener {

            (it.tag as? PoiItem)?.latLonPoint?.runCatching {
                startActivity(MapUtils.queryNavigation(latitude, longitude))
            }

        }

        mapView?.map?.runCatching {

            setOnMarkerClickListener(this@LbsBaseMapFragment)

            setOnCameraChangeListener(this@LbsBaseMapFragment)
            setLocationSource(this@LbsBaseMapFragment)

            uiSettings?.isZoomControlsEnabled = false
            //uiSettings.isMyLocationButtonEnabled = true
            isMyLocationEnabled = true



            LocManager.getInstance().currentLocation?.let {
                val latLng = LatLng(it.latitude, it.longitude)
                moveCamera(CameraUpdateFactory.newLatLngZoom(
                        latLng, getZoom()))
            }


        }
    }

    override fun onLocationChanged(amapLocation: AMapLocation?) {

        if (mListener !=null && amapLocation?.errorCode == 0){
            updateLocation(amapLocation)
        }

    }
    override fun onMarkerClick(marker: Marker?): Boolean {

        val idx = markerOverlay?.getPoiIndex(marker)?:return false

        markerOverlay?.getPoiItem(idx)?.let {
            Timber.e("-----$it")
            if (!rl_bottom_lbs.isShown){
                rl_bottom_lbs.visible()
            }

            tv_address_title.text = it.title
            tv_address_info.text = it.snippet
            fab_navigation.setTag(it)
        }

        return true
    }

    override fun deactivate() {

        mListener = null
        amaplocationClient?.let {
            it.stopLocation()
            it.onDestroy()
        }

        amaplocationClient = null
    }

    override fun activate(listener: LocationSource.OnLocationChangedListener?) {
        mListener = listener

        if (amaplocationClient == null){

            AMapLocationClient(context).apply {

                setLocationListener(this@LbsBaseMapFragment)

                setLocationOption(AMapLocationClientOption().apply {
                    locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
                    isOnceLocation = true
                })

            }.also {
                it.startLocation()
                amaplocationClient = it
            }

        }

    }


    override fun onCameraChangeFinish(cameraPosition: CameraPosition?) {

        if (isVisible){
            Timber.e("onCameraChangeFinish --> $cameraPosition   $this")
            cameraPosition?.target?.let {
                onLoadPoiItems(LatLonPoint(it.latitude,it.longitude))
            }

            rl_bottom_lbs.gone()
        }
    }

    override fun onCameraChange(cameraPosition: CameraPosition?) {
        rl_bottom_lbs.gone()
    }


    protected open fun onLoadPoiItems(point: LatLonPoint){


        if (lbsViewModel.point != point){
            lbsViewModel.point = point
            lbsViewModel.reset()


            mLocLatLng?.let {

                addMarker(it)
            }
        }

    }

    private fun updateLocation(amapLocation: AMapLocation){

        val location = LatLng(amapLocation.latitude, amapLocation.longitude)

        mLocLatLng = location
        if (!firstFix) {
            firstFix = true

            onLoadPoiItems( LatLonPoint(location.latitude, location.longitude))


            addCircle(location, amapLocation.accuracy.toDouble())
            addMarker(location)

            sensorHelper.setCurrentMarker(mLocMarker)

            mapView?.map?.moveCamera(CameraUpdateFactory.newLatLngZoom(location, getZoom()));
        } else {

            mCircle?.center = location;
            mCircle?.radius = amapLocation.accuracy.toDouble();
            mLocMarker?.position = location;

            mapView?.map?.moveCamera(CameraUpdateFactory.changeLatLng(location));
        }

    }

    private fun showPoints(list:List<PoiItem>?){

        markerOverlay?.removeFromMap()

        markerOverlay = GasPoiOverlay(mapView?.map,list,getOverlayType()).apply {

            addToMap()
            //zoomToSpan()
        }

    }


    private fun addCircle(latlng: LatLng, radius: Double) {
        val options = CircleOptions().apply {
            strokeWidth(1f)
            fillColor(Color.argb(10, 0, 0, 180))
            strokeColor(LottieProperty.STROKE_COLOR)
            center(latlng)
            radius(radius)
        }

        mCircle = mapView?.map?.addCircle(options)
    }

    private fun addMarker(latlng: LatLng) {
        if (mLocMarker != null) {
            return
        }
        val options = MarkerOptions().apply {
            icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(resources,
                    R.mipmap.navi_map_gps_locked)))
            anchor(0.5f, 0.5f)
            position(latlng)
        }

        mLocMarker = mapView?.map?.addMarker(options)
    }


    override fun onResume() {
        super.onResume()
        mapView?.onResume()
        if (this::sensorHelper.isInitialized){
            sensorHelper.registerSensorListener()
        }
    }


    override fun onPause() {
        super.onPause()

        if (this::sensorHelper.isInitialized){

            sensorHelper.unRegisterSensorListener()
            sensorHelper.setCurrentMarker(null)
        }
        mapView?.onPause()
        deactivate()
        firstFix = false
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        mapView?.onSaveInstanceState(outState)
    }

    override fun onDestroy() {
        super.onDestroy()
        mapView?.onDestroy()
    }


    protected open fun getZoom():Float = 15f

    protected open fun getOverlayType():Int = 0
}